package com.unknown

import com.unknown.domain.repository.NotFoundException
import com.unknown.world.Room
import com.unknown.world.RoomTile
import grails.converters.JSON
import grails.plugins.springsecurity.Secured
import org.apache.commons.logging.Log
import org.codehaus.groovy.grails.web.json.JSONObject
import org.apache.commons.logging.LogFactory
import com.unknown.world.Tile

class RoomController {

	def roomService
	def tileService

    def index = { }
		
	def notFound = {}
	
	static final int UP = 4
	static final int DOWN = 8
	static final int LEFT = 1
	static final int RIGHT = 2
	
	def opposite(def dir){
		def op = 0;
		if( (dir & UP ) == UP ){
			op = DOWN
		}
		if( (dir & DOWN ) == DOWN ){
			op = UP
		}
		if( (dir & LEFT ) == LEFT ){
			op = op | RIGHT
		}
		if( (dir & RIGHT ) == RIGHT ){
			op = op | LEFT
		}
		return op;
	}
	
	def createNeighbor(Room origin, def offset){		
		Room room = new Room();
		room.origin = origin;
		room.name  = offset;
		room.row = offset.y
		room.column = offset.x
		
		roomService.save(room);

        log.debug("[Created] Room.id=${room.id}, Room.name=${room.name}")

		return room;
	}

    @Secured(['ROLE_ADMIN', 'ROLE_USER'])
	def show = {
		validate(params, 'id') 
		def offsetX = params.offsetX ? params.getInt('offsetX') : 0
		def offsetY = params.offsetY ? params.getInt('offsetY') : 0
		
		def offset = [x:offsetX, y:offsetY]

        if( offset.y == null || offset.x == null ){
            throw new RuntimeException("Offset is null : " + offset);
        }

		def lookingForNeighbor = (offsetX || offsetY)
		Room room = roomService.findById(params.id)
		Room neighbor = room;		
		if( !room ){
            log.error("Room not found: ${params.id}");
			throw new RuntimeException("Room not found: " + params.id)
		}		
		if( lookingForNeighbor ){
			offset.x = offset.x + room.column
			offset.y = offset.y + room.row

			neighbor = Room.findNeighbor(room.origin, offset.x, offset.y)
						
			if( !neighbor ){
                log.debug("Neighbor doesn't exist. Creating...");
				neighbor = createNeighbor(room.origin, offset);
			}
		}
		if( !neighbor ) throw new RuntimeException("Failed to create neighbor");
		return ['room':neighbor]
	}

    @Secured(['ROLE_ADMIN', 'ROLE_USER'])
	def showJSON = {
		validate(params, 'id')
		
		Room room = roomService.findById(params.id)
		render room as JSON
	}
	
	
	@Secured(['ROLE_ADMIN'])
	def edit = {
		validate(params, 'id')
		
		Room room = roomService.findById(params.id)
        if( room )
            return ['room':room, 'rooms':roomService.findAll()]
        throw new NotFoundException();
	}
	
	@Secured(['ROLE_ADMIN'])
	def create = {
		Room room = new Room(params['room'])
		
		validate(room, 'entityId')
		validate(room, 'name')
		
		room.origin = room
		
		try{
			room = roomService.findById( room.entityId )
			if( room ){
                log.warn("Room already exists. Id=${room.entityId}");
			}else{
				room = new Room(params['room'])
				room.origin = room
				roomService.save(room)
			}
		}catch(NotFoundException e){
			roomService.save(room)
		}
		redirect(action:list)
	}
	
	@Secured(['ROLE_ADMIN', 'ROLE_USER'])
	def update = {
		def tiles = null;
		def erased = null;
		if( params.tiles ){
			tiles = JSON.parse(params.tiles);
		}
		if( params.erased ){
			erased = JSON.parse(params.erased);
		}
		
		println( "Updated: ${tiles}" );
		println( "Erased : ${erased}" );
		
		tiles.values().each {
			if( !it || it == JSONObject.NULL || !it.imageId ) return;
			
			Room room = roomService.findById(it.roomId)
			//if( it.name ) room.name = it.name;
			//if( it.description ) room.description = it.description;
			if( !room.tiles ) room.tiles = [];

            Tile tile = tileService.findByEntityId(it.imageId)
            if( !tile )
                return;
			def roomTile = new RoomTile(row: it.row, col: it.col, tile:tile);
			if( room.tiles.contains(roomTile) ){
				room.tiles.remove(roomTile);
			}
			room.tiles.add(roomTile);
			roomService.save(room);
		}
		erased.values().each {
			if( !it || it == JSONObject.NULL ) return;
			
			Room room = roomService.findById(it.roomId)
			if( !room.tiles ) return;
			
			def roomTile = new RoomTile(row: it.row, col: it.col);
			if( room.tiles.contains(roomTile) ){
				room.tiles.remove(roomTile);
			}
			roomService.save(room);
		}
		def result = ['msg':'success']
		
		render result as JSON
	}

    @Secured(['ROLE_ADMIN', 'ROLE_USER'])
	def menus = {
		List<Room> rooms = roomService.findAll()
		
		return ['rooms':rooms]
	}

    @Secured(['ROLE_ADMIN', 'ROLE_USER'])
	def list = {
		List<Room> rooms = roomService.findAll()
		
		return ['rooms':rooms]
	}
	
	def validate(def params, String param){
		if(!params[param])
			throw new NotFoundException(param);
	}
}
